function Compliance(proposition, authority) {
	var part =  new Array('<cc:compliance xmlns:cc="urn:frog">',
		proposition,
		'<cc:assent>',
		authority,
		'</cc:assent>',
		'sig',
		'</cc:compliance>');

	var self = this;

	this.toString = function() {
		return part.join("");
	}

	this.toSign = function() {
		var ret = "";
		for(var i = 0; i < part.length; i++)
			if(i != 5)
				ret += part[i];
		return ret;
	}

	this.sign = function(cb) {
		var ct = crypto.signText(self.toSign(), "auto");
		convertRequest(ct, function(x) {
			part[5] = x;
			cb(self);
		});
	}
}

function Proposition(req) {
	var doc, text, currency, payment, quota;

	this.getCurrency = function () { return currency; }
	this.getQuota = function () { return quota; }
	this.getPayment = function () { return payment; }

	doc = req.responseXML;
	text = req.responseText;

	var e = doc.getElementsByTagName("condition");
	if(e.length > 0) {
		var rem = e[0].getElementsByTagName("remuneration");
		if(rem.length > 0) {
			var amt = rem[0].getElementsByTagName("amount");
			var q = rem[0].getElementsByTagName("ratingQuantum");
			if((amt.length > 0) && (q.length > 0)) {
				currency =  amt[0].getAttribute("currency");
				payment = amt[0].firstChild.nodeValue;
				quota = q[0].firstChild.nodeValue;
			}
		}
	}

	this.toString = function() { return text; }
}

function Authority(recipient, amount, currency, notbefore, notafter) {
	var part =  new Array('<dosh:authority xmlns:dosh="urn:dosh"><dosh:recipient>',
	recipient,
	'</dosh:recipient><dosh:amount currency="', // 2
	currency,
	'">',
	amount,
	'</dosh:amount><dosh:validityInterval><dosh:notBefore>', // 6
	notbefore,
	'</dosh:notBefore><dosh:notAfter>',
	notafter,
	'</dosh:notAfter></dosh:validityInterval>', // 10
	'sig',
	'</dosh:authority>');

	var self = this;

	this.toString = function() {
		return part.join("");
	}

	this.toSign = function() {
		var ret = "";
		for(var i = 0; i < part.length; i++)
			if(i != 11)
				ret += part[i];
		return ret;
	}

	this.sign = function(cb) {
		var ct = crypto.signText(self.toSign(), "auto");
		convertRequest(ct, function(x) {
			part[11] = x;
			cb(self);
		});
	}
}
function padDate(num) {
	if(num < 10)
		return "0" + num;
	else
		return num;
}

function isoDate(offsetms) {
	var d = new Date();
	d.setTime(d.getTime() + offsetms);
	var ret = d.getUTCFullYear() + "-" + padDate(1 + d.getUTCMonth()) + "-" + 
		padDate(d.getUTCDate()) + "T" + padDate(d.getUTCHours()) + ":" + 
		padDate(d.getUTCMinutes()) + ":" + padDate(d.getUTCSeconds()) + "Z";
	return ret;
}


function dispatchSoap(url, message, update) {
	var x = new XMLHttpRequest();
	var soapstart = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body>";
	var soapend = "</soapenv:Body></soapenv:Envelope>";
	var body = soapstart + message + soapend;
        x.open("POST", url, true);
	x.setRequestHeader('SOAPAction', '""');
        x.setRequestHeader('Content-Type', 'text/xml');
        x.onreadystatechange = function() {
                switch(x.readyState) {
                        case 4:
                                // document.getElementById(update).value = x.responseText;
				update(x);
                                break;
                }
        }
        x.send(body);
}

function dispatchAll(url, message, update) {
	var x = new XMLHttpRequest();
        x.open("POST", url, true);
        x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        x.onreadystatechange = function() {
                switch(x.readyState) {
                        case 4:
                                // document.getElementById(update).value = x.responseText;
				update(x);
                                break;
                }
        }
        x.send(message);
}

function dispatch(url, message, update) {
	var x = new XMLHttpRequest();
        x.open("POST", url, true);
        x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        x.onreadystatechange = function() {
                switch(x.readyState) {
                        case 4:
                                // document.getElementById(update).value = x.responseText;
				update(x.responseText);
                                break;
                }
        }
        x.send(message);
}


function convertRequest(request, update) {
	dispatch("/pkcs/PKCSToXMLDSig", 'signature='+encodeURIComponent(request), function (x) { 
		var end = x.indexOf("?>");
		if(end > 0)
			x = x.substring(end + 2);
		update(x);
		});
}

function makeSign(self, part, index) {
	return function(cb) {
		var ct = crypto.signText(self.toSign(), "auto");
		if('error:' == ct.substring(0, 6)) 
			throw new Error(ct.substring(6));
		convertRequest(ct, function(x) {
			part[index] = x;
			cb(self);
		});
	}
}

function Solicitation(address) {
	var part =  new Array('<ch:solicitation xmlns:ch="urn:frog"><ch:Address>',
		address,
		'</ch:Address>',
		'sig',
		'</ch:solicitation>');

	var self = this;

	this.toString = function() {
		return part.join("");
	}

	this.toSign = function() {
		var ret = "";
		for(var i = 0; i < part.length; i++)
			if(i != 3)
				ret += part[i];
		return ret;
	}

	this.sign = makeSign(self, part, 3);
	this.oldsign = function(cb) {
		var ct = crypto.signText(self.toSign(), "auto");
		convertRequest(ct, function(x) {
			part[3] = x;
			cb(self);
		});
	}
}

function setid(id, value) {
	document.getElementById(id).value = value;
}

function getid(id) {
	return document.getElementById(id).value;
}
